using Microsoft.EntityFrameworkCore;
using WMS_Goodsinfo.Api.Write.DTOs;
using WMS_Goodsinfo.Infastructure;

namespace WMS_Goodsinfo.Api.Write.Services
{
    /// <summary>
    /// 仪表板统计服务实现
    /// </summary>
    public class DashboardStatisticsService : IDashboardStatisticsService
    {
        private readonly ProductDbContext _dbContext;
        private readonly ILogger<DashboardStatisticsService> _logger;

        // 预定义颜色
        private readonly string[] _colors = {
            "#5470c6", "#91cc75", "#fac858", "#ee6666", "#73c0de", 
            "#3ba272", "#fc8452", "#9a60b4", "#ea7ccc", "#ffb347"
        };

        public DashboardStatisticsService(ProductDbContext dbContext, ILogger<DashboardStatisticsService> logger)
        {
            _dbContext = dbContext;
            _logger = logger;
        }
        /// <summary>
        /// 库存占比统计
        /// </summary>
        /// <returns></returns>
        public async Task<InventoryProportionData> GetInventoryProportionAsync()
        {
            try
            {
                _logger.LogInformation("开始获取库存占比数据");

                // 获取所有商品的库存信息
                var products = await _dbContext.product_Table
                    .Where(p => !p.IsDelete && p.Current_Inventory > 0)
                    .Select(p => new
                    {
                        p.Id,
                        p.ProductName,
                        p.Current_Inventory,
                        Price = p.TotalMoeny / Math.Max(p.Current_Inventory, 1) // 计算单价
                    })
                    .ToListAsync();

                var quantityData = new List<ProportionItem>();
                var amountData = new List<ProportionItem>();
                var totalQuantity = products.Sum(p => p.Current_Inventory);
                var totalAmount = products.Sum(p => p.Current_Inventory * p.Price);

                // 按商品分组统计
                for (int i = 0; i < Math.Min(products.Count, 10); i++)
                {
                    var product = products[i];
                    
                    quantityData.Add(new ProportionItem
                    {
                        Name = product.ProductName ?? $"商品{product.Id}",
                        Value = product.Current_Inventory,
                        Color = _colors[i % _colors.Length]
                    });

                    var productAmount = product.Current_Inventory * product.Price;
                    amountData.Add(new ProportionItem
                    {
                        Name = product.ProductName ?? $"商品{product.Id}",
                        Value = productAmount,
                        Color = _colors[i % _colors.Length]
                    });
                }

                _logger.LogInformation($"库存占比数据获取成功，总库存：{totalQuantity}，总金额：{totalAmount}");

                return new InventoryProportionData
                {
                    Timestamp = DateTime.Now,
                    QuantityData = quantityData,
                    AmountData = amountData,
                    TotalQuantity = totalQuantity,
                    TotalAmount = totalAmount
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取库存占比数据失败");
                return new InventoryProportionData { Timestamp = DateTime.Now };
            }
        }
        /// <summary>
        /// 入库统计
        /// </summary>
        /// <param name="days"></param>
        /// <returns></returns>
        public async Task<InboundStatisticsData> GetInboundStatisticsAsync(int days = 7)
        {
            try
            {
                _logger.LogInformation($"开始获取{days}天入库统计数据");

                var startDate = DateTime.Today.AddDays(-days + 1);
                var endDate = DateTime.Today.AddDays(1);

                // 获取入库数据
                var inboundData = await _dbContext.inOuts
                    .Where(io => !io.IsDelete && 
                                io.InOutType == "入库" && 
                                !string.IsNullOrEmpty(io.InOutTiem))
                    .ToListAsync();

                // 在内存中处理日期解析和过滤
                var filteredData = inboundData
                    .Where(io => DateTime.TryParse(io.InOutTiem, out var date) && 
                                date >= startDate && date < endDate)
                    .GroupBy(io => DateTime.Parse(io.InOutTiem).Date)
                    .Select(g => new StatisticsItem
                    {
                        Date = g.Key.ToString("yyyy-MM-dd"),
                        Quantity = g.Sum(io => io.InNumber),
                        Amount = g.Sum(io => io.InMoney),
                        Count = g.Count()
                    })
                    .OrderBy(s => s.Date)
                    .ToList();

                // 补齐缺失的日期
                var completeData = new List<StatisticsItem>();
                for (int i = 0; i < days; i++)
                {
                    var currentDate = startDate.AddDays(i);
                    var dateStr = currentDate.ToString("yyyy-MM-dd");
                    var existingData = filteredData.FirstOrDefault(d => d.Date == dateStr);
                    
                    completeData.Add(existingData ?? new StatisticsItem
                    {
                        Date = dateStr,
                        Quantity = 0,
                        Amount = 0,
                        Count = 0
                    });
                }

                var summary = new StatisticsSummary
                {
                    TotalQuantity = completeData.Sum(d => d.Quantity),
                    TotalAmount = completeData.Sum(d => d.Amount),
                    TotalCount = completeData.Sum(d => d.Count),
                    AvgQuantity = completeData.Count > 0 ? (decimal)completeData.Average(d => d.Quantity) : 0,
                    AvgAmount = completeData.Count > 0 ? completeData.Average(d => d.Amount) : 0
                };

                _logger.LogInformation($"入库统计数据获取成功，总入库量：{summary.TotalQuantity}");

                return new InboundStatisticsData
                {
                    Timestamp = DateTime.Now,
                    TimeRange = $"最近{days}天",
                    ChartData = completeData,
                    Summary = summary
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取{days}天入库统计数据失败");
                return new InboundStatisticsData { Timestamp = DateTime.Now, TimeRange = $"最近{days}天" };
            }
        }
        /// <summary>
        /// 出库统计
        /// </summary>
        /// <param name="days"></param>
        /// <returns></returns>
        public async Task<OutboundStatisticsData> GetOutboundStatisticsAsync(int days = 7)
        {
            try
            {
                _logger.LogInformation($"开始获取{days}天出库统计数据");

                var startDate = DateTime.Today.AddDays(-days + 1);
                var endDate = DateTime.Today.AddDays(1);

                // 获取出库数据
                var outboundData = await _dbContext.inOuts
                    .Where(io => !io.IsDelete && 
                                io.InOutType == "出库" && 
                                !string.IsNullOrEmpty(io.InOutTiem))
                    .ToListAsync();

                // 在内存中处理日期解析和过滤
                var filteredData = outboundData
                    .Where(io => DateTime.TryParse(io.InOutTiem, out var date) && 
                                date >= startDate && date < endDate)
                    .GroupBy(io => DateTime.Parse(io.InOutTiem).Date)
                    .Select(g => new StatisticsItem
                    {
                        Date = g.Key.ToString("yyyy-MM-dd"),
                        Quantity = g.Sum(io => io.OutNumbber),
                        Amount = g.Sum(io => io.OutMoney),
                        Count = g.Count()
                    })
                    .OrderBy(s => s.Date)
                    .ToList();

                // 补齐缺失的日期
                var completeData = new List<StatisticsItem>();
                for (int i = 0; i < days; i++)
                {
                    var currentDate = startDate.AddDays(i);
                    var dateStr = currentDate.ToString("yyyy-MM-dd");
                    var existingData = filteredData.FirstOrDefault(d => d.Date == dateStr);
                    
                    completeData.Add(existingData ?? new StatisticsItem
                    {
                        Date = dateStr,
                        Quantity = 0,
                        Amount = 0,
                        Count = 0
                    });
                }

                var summary = new StatisticsSummary
                {
                    TotalQuantity = completeData.Sum(d => d.Quantity),
                    TotalAmount = completeData.Sum(d => d.Amount),
                    TotalCount = completeData.Sum(d => d.Count),
                    AvgQuantity = completeData.Count > 0 ? (decimal)completeData.Average(d => d.Quantity) : 0,
                    AvgAmount = completeData.Count > 0 ? completeData.Average(d => d.Amount) : 0
                };

                _logger.LogInformation($"出库统计数据获取成功，总出库量：{summary.TotalQuantity}");

                return new OutboundStatisticsData
                {
                    Timestamp = DateTime.Now,
                    TimeRange = $"最近{days}天",
                    ChartData = completeData,
                    Summary = summary
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取{days}天出库统计数据失败");
                return new OutboundStatisticsData { Timestamp = DateTime.Now, TimeRange = $"最近{days}天" };
            }
        }
        /// <summary>
        /// 排行统计
        /// </summary>
        /// <param name="days"></param>
        /// <param name="topCount"></param>
        /// <returns></returns>
        public async Task<RankingData> GetRankingDataAsync(int days = 7, int topCount = 10)
        {
            try
            {
                _logger.LogInformation($"开始获取{days}天排行榜数据");

                var startDate = DateTime.Today.AddDays(-days + 1);
                var endDate = DateTime.Today.AddDays(1);

                // 获取出入库数据
                var inOutData = await _dbContext.inOuts
                    .Where(io => !io.IsDelete && !string.IsNullOrEmpty(io.InOutTiem))
                    .ToListAsync();

                // 获取商品信息
                var products = await _dbContext.product_Table
                    .Where(p => !p.IsDelete)
                    .ToDictionaryAsync(p => p.Id, p => p.ProductName);

                // 在内存中处理日期过滤
                var filteredData = inOutData
                    .Where(io => DateTime.TryParse(io.InOutTiem, out var date) && 
                                date >= startDate && date < endDate)
                    .ToList();

                // 入库排行
                var inboundRanking = filteredData
                    .Where(io => io.InOutType == "入库")
                    .GroupBy(io => io.ProductI_Id)
                    .Select(g => new
                    {
                        ProductId = g.Key,
                        Quantity = g.Sum(io => io.InNumber),
                        Amount = g.Sum(io => io.InMoney),
                        Count = g.Count()
                    })
                    .OrderByDescending(r => r.Quantity)
                    .Take(topCount)
                    .Select((r, index) => new RankingItem
                    {
                        Rank = index + 1,
                        ProductId = r.ProductId,
                        ProductName = products.ContainsKey(r.ProductId) ? products[r.ProductId] : $"商品{r.ProductId}",
                        Quantity = r.Quantity,
                        Amount = r.Amount,
                        Count = r.Count
                    })
                    .ToList();

                // 出库排行
                var outboundRanking = filteredData
                    .Where(io => io.InOutType == "出库")
                    .GroupBy(io => io.ProductI_Id)
                    .Select(g => new
                    {
                        ProductId = g.Key,
                        Quantity = g.Sum(io => io.OutNumbber),
                        Amount = g.Sum(io => io.OutMoney),
                        Count = g.Count()
                    })
                    .OrderByDescending(r => r.Quantity)
                    .Take(topCount)
                    .Select((r, index) => new RankingItem
                    {
                        Rank = index + 1,
                        ProductId = r.ProductId,
                        ProductName = products.ContainsKey(r.ProductId) ? products[r.ProductId] : $"商品{r.ProductId}",
                        Quantity = r.Quantity,
                        Amount = r.Amount,
                        Count = r.Count
                    })
                    .ToList();

                _logger.LogInformation($"排行榜数据获取成功，入库排行{inboundRanking.Count}条，出库排行{outboundRanking.Count}条");

                return new RankingData
                {
                    Timestamp = DateTime.Now,
                    InboundRanking = inboundRanking,
                    OutboundRanking = outboundRanking
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"获取{days}天排行榜数据失败");
                return new RankingData { Timestamp = DateTime.Now };
            }
        }
        /// <summary>
        /// 检测系统消息
        /// </summary>
        /// <returns></returns>
        public async Task<List<SystemMessage>> CheckSystemMessagesAsync()
        {
            try
            {
                _logger.LogInformation("开始检查系统消息");

                var messages = new List<SystemMessage>();

                // 检查库存预警 (简化版，使用固定阈值)
                var lowInventoryProducts = await _dbContext.product_Table
                    .Where(p => !p.IsDelete && p.Current_Inventory <= 10) // 使用固定阈值10
                    .Select(p => new { p.ProductName, p.Current_Inventory })
                    .ToListAsync();

                foreach (var product in lowInventoryProducts)
                {
                    messages.Add(new SystemMessage
                    {
                        Type = "warning",
                        Title = "库存预警",
                        Content = $"{product.ProductName} 库存不足，当前库存：{product.Current_Inventory}",
                        Timestamp = DateTime.Now,
                        AutoClose = false,
                        Data = new Dictionary<string, object>
                        {
                            ["productName"] = product.ProductName,
                            ["currentInventory"] = product.Current_Inventory
                        }
                    });
                }

                // 检查高库存预警 (简化版，使用固定阈值)
                var highInventoryProducts = await _dbContext.product_Table
                    .Where(p => !p.IsDelete && p.Current_Inventory >= 1000) // 使用固定阈值1000
                    .Select(p => new { p.ProductName, p.Current_Inventory })
                    .ToListAsync();

                foreach (var product in highInventoryProducts)
                {
                    messages.Add(new SystemMessage
                    {
                        Type = "info",
                        Title = "库存提醒",
                        Content = $"{product.ProductName} 库存较高，当前库存：{product.Current_Inventory}",
                        Timestamp = DateTime.Now,
                        AutoClose = true,
                        Data = new Dictionary<string, object>
                        {
                            ["productName"] = product.ProductName,
                            ["currentInventory"] = product.Current_Inventory
                        }
                    });
                }

                // 检查今日异常操作（可以根据业务需求自定义）
                var today = DateTime.Today;
                var todayInOuts = await _dbContext.inOuts
                    .Where(io => !io.IsDelete && !string.IsNullOrEmpty(io.InOutTiem))
                    .ToListAsync();

                var todayOperations = todayInOuts
                    .Where(io => DateTime.TryParse(io.InOutTiem, out var date) && date.Date == today)
                    .ToList();

                if (todayOperations.Any())
                {
                    var totalInbound = todayOperations.Where(io => io.InOutType == "入库").Sum(io => io.InNumber);
                    var totalOutbound = todayOperations.Where(io => io.InOutType == "出库").Sum(io => io.OutNumbber);

                    if (totalInbound > 0 || totalOutbound > 0)
                    {
                        messages.Add(new SystemMessage
                        {
                            Type = "success",
                            Title = "今日业务统计",
                            Content = $"今日入库 {totalInbound} 件，出库 {totalOutbound} 件",
                            Timestamp = DateTime.Now,
                            AutoClose = true,
                            Data = new Dictionary<string, object>
                            {
                                ["todayInbound"] = totalInbound,
                                ["todayOutbound"] = totalOutbound,
                                ["operationCount"] = todayOperations.Count
                            }
                        });
                    }
                }

                _logger.LogInformation($"系统消息检查完成，生成{messages.Count}条消息");

                return messages;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查系统消息失败");
                return new List<SystemMessage>();
            }
        }

        public async Task<DashboardData> GetDashboardDataAsync()
        {
            try
            {
                _logger.LogInformation("开始获取完整仪表板数据");

                // 并行获取所有数据
                var inventoryTask = GetInventoryProportionAsync();
                var inboundTask = GetInboundStatisticsAsync();
                var outboundTask = GetOutboundStatisticsAsync();
                var rankingTask = GetRankingDataAsync();
                var messagesTask = CheckSystemMessagesAsync();

                await Task.WhenAll(inventoryTask, inboundTask, outboundTask, rankingTask, messagesTask);

                var dashboardData = new DashboardData
                {
                    Timestamp = DateTime.Now,
                    InventoryProportion = await inventoryTask,
                    InboundStatistics = await inboundTask,
                    OutboundStatistics = await outboundTask,
                    Ranking = await rankingTask,
                    SystemMessages = await messagesTask
                };

                _logger.LogInformation("完整仪表板数据获取成功");

                return dashboardData;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取完整仪表板数据失败");
                return new DashboardData { Timestamp = DateTime.Now };
            }
        }
    }
}